package com.wechat.pay.contrib.apache.httpclient;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.wechat.pay.contrib.apache.httpclient.auth.CertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.HttpHost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.execchain.ClientExecChain;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.List;

/**
 * @author xy-peng
 */
public class WechatPayHttpClientBuilder extends HttpClientBuilder {

    private static final String OS = System.getProperty("os.name") + "/" + System.getProperty("os.version");
    private static final String VERSION = System.getProperty("java.version");
    private Credentials credentials;
    private Validator validator;


    private WechatPayHttpClientBuilder() {
        super();

        String userAgent = String.format(
                "WechatPay-Apache-HttpClient/%s (%s) Java/%s",
                getClass().getPackage().getImplementationVersion(),
                OS,
                VERSION == null ? "Unknown" : VERSION);
        setUserAgent(userAgent);
    }

    public static WechatPayHttpClientBuilder create() {
        return new WechatPayHttpClientBuilder();
    }

    public WechatPayHttpClientBuilder withMerchant(String merchantId, String serialNo, PrivateKey privateKey) {
        this.credentials = new WechatPay2Credentials(merchantId, new PrivateKeySigner(serialNo, privateKey));
        return this;
    }

    public WechatPayHttpClientBuilder withCredentials(Credentials credentials) {
        this.credentials = credentials;
        return this;
    }

    public WechatPayHttpClientBuilder withWechatPay(List<X509Certificate> certificates) {
        this.validator = new WechatPay2Validator(new CertificatesVerifier(certificates));
        return this;
    }

    public WechatPayHttpClientBuilder withProxy(HttpHost proxy) {
        if (proxy != null) {
            this.setProxy(proxy);
        }
        return this;
    }

    /**
     * Please use {@link #withWechatPay(List)} instead
     *
     * @param certificates 平台证书list
     * @return 具有验证器的builder
     */
    @SuppressWarnings("SpellCheckingInspection")
    @Deprecated
    public WechatPayHttpClientBuilder withWechatpay(List<X509Certificate> certificates) {
        return withWechatPay(certificates);
    }

    public WechatPayHttpClientBuilder withValidator(Validator validator) {
        this.validator = validator;
        return this;
    }

    @Override
    public CloseableHttpClient build() {
        if (credentials == null) {
            throw new IllegalArgumentException("缺少身份认证信息");
        }
        if (validator == null) {
            throw new IllegalArgumentException("缺少签名验证信息");
        }
        return super.build();
    }

    @Override
    protected ClientExecChain decorateProtocolExec(final ClientExecChain requestExecutor) {
        return new SignatureExec(this.credentials, this.validator, requestExecutor);
    }

//    public static void main(String[] args) throws IOException {
//        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
//                new FileInputStream("D:\\down\\WXCertUtil\\cert\\apiclient_key.pem"));
//        CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
//                .withMerchant("1632010016", "7756CC99D32B941BAA8D2EF42401E98F28C35EF6", merchantPrivateKey)
//                .withValidator(response -> true) // NOTE: 设置一个空的应答签名验证器，**不要**用在业务请求
//                .build();
//        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
//        httpPost.addHeader("Accept", "application/json");
//        httpPost.addHeader("Content-type","application/json; charset=utf-8");
//
//        ByteArrayOutputStream bos = new ByteArrayOutputStream();
//        ObjectMapper objectMapper = new ObjectMapper();
//
//        ObjectNode rootNode = objectMapper.createObjectNode();
//        rootNode.put("mchid","1632010016")
//                .put("appid", "wxfe37ddbe2dde921b")
//                .put("description", "李哥 新年好")
//                .put("notify_url", "https://www.weixin.qq.com/wxpay/pay.php")
//                .put("out_trade_no", "L202209150002");
//        rootNode.putObject("amount")
//                .put("total", 100);
//
//
//        objectMapper.writeValue(bos, rootNode);
//
//        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
//        CloseableHttpResponse response = httpClient.execute(httpPost);
//
//        String bodyAsString = EntityUtils.toString(response.getEntity());
//        System.out.println(bodyAsString);
//    }

    /**
     * 扫码
     * @param args
     * @throws IOException
     */
//    public static void main(String[] args) throws IOException {
//        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
//                new FileInputStream("D:\\down\\WXCertUtil\\cert\\apiclient_key.pem"));
//        CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
//                .withMerchant("1632010016", "7756CC99D32B941BAA8D2EF42401E98F28C35EF6", merchantPrivateKey)
//                .withValidator(response -> true) // NOTE: 设置一个空的应答签名验证器，**不要**用在业务请求
//                .build();
//        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
//        httpPost.addHeader("Accept", "application/json");
//        httpPost.addHeader("Content-type","application/json; charset=utf-8");
//
//        ByteArrayOutputStream bos = new ByteArrayOutputStream();
//        ObjectMapper objectMapper = new ObjectMapper();
//
//        ObjectNode rootNode = objectMapper.createObjectNode();
//        rootNode.put("mchid","1632010016")
//                .put("appid", "wxfe37ddbe2dde921b")
//                .put("description", "李哥 新年好")
//                .put("notify_url", "https://www.weixin.qq.com/wxpay/pay.php")
//                .put("out_trade_no", "L202209150003");
//        rootNode.putObject("amount")
//                .put("total", 100);
//
//
//        objectMapper.writeValue(bos, rootNode);
//
//        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
//        CloseableHttpResponse response = httpClient.execute(httpPost);
//
//        String bodyAsString = EntityUtils.toString(response.getEntity());
//        System.out.println(bodyAsString);
//    }
    public static void main(String[] args) throws IOException {
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
                new FileInputStream("D:\\down\\WXCertUtil\\cert\\apiclient_key.pem"));
        CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                .withMerchant("1632010016", "7756CC99D32B941BAA8D2EF42401E98F28C35EF6", merchantPrivateKey)
                .withValidator(response -> true) // NOTE: 设置一个空的应答签名验证器，**不要**用在业务请求
                .build();
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/h5");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectMapper objectMapper = new ObjectMapper();

        ObjectNode rootNode = objectMapper.createObjectNode();
        rootNode.put("mchid","1632010016")
                .put("appid", "wxfe37ddbe2dde921b")
                .put("description", "李哥 新年好")
                .put("notify_url", "https://www.baidu.com")
                .put("out_trade_no", "L202209170002");
        rootNode.putObject("amount")
                .put("total", 100);
        rootNode.putObject("scene_info")
                .put("payer_client_ip", "120.76.207.91")
                .putObject("h5_info")
                    .put("type", "Wap");



        objectMapper.writeValue(bos, rootNode);

        httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
        CloseableHttpResponse response = httpClient.execute(httpPost);

        String bodyAsString = EntityUtils.toString(response.getEntity());
        System.out.println(bodyAsString);
    }
}
